<template>
  <!--    @keydown.native.capture.stop 阻止方向键移动菜单-->
  <div class="widget-tree-container">
    <el-tree
      ref="widgetTree"
      node-key="id"
      :lazy="true"
      :load="loadNode"
      :props="{label: 'name', isLeaf: judgeLeafNode}"
      :draggable="true"
      :expand-on-click-node="false"
      :auto-expand-parent="false"
      :highlight-current="true"
      :accordion="false"
      :default-expanded-keys="expandedKey"
      :allow-drag="allowDrag"
      :allow-drop="allowDrop"
      @node-expand="nodeExpand"
      @node-collapse="nodeCollapse"
      @node-drag-start="nodeDragStart"
      @node-drag-end="nodeDragEnd"
      @node-drop="nodeDrop"
      @node-click="nodeClick">
      <div
        slot-scope="{data}"
        v-if="!data.isDeleted"
        :id="`treeNode-${data.id}`"
        :class="[nodeClass(data), isSorting ? 'cursor-all-scroll' : 'cursor-pointer']"
        class="custom-tree-node">
        <div class="flex-justify-start">
          <i v-if="data.id === homePageId" class="el-icon-s-home mar-rgt-5"></i>
          <span class="custom-tree-name">{{data.name}}</span>
        </div>
        <div v-if="showDropdown(data)" @click.stop="">
          <el-dropdown
            trigger="click"
            @command="(command) => pageOperation(data, command)">
            <div class="flex-justify-end pad-top-btm-5">
              <i class="el-icon-more font-size-16"></i>
            </div>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item
                v-for="item in dropdownItems(data)"
                :key="item.command" :command="item.command">
                <span :class="item.class">{{item.label}}</span>
              </el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </div>
        <div v-if="!data.isRoot" class="flex-justify-end">
          <i :class="!data.display ? 'icon-Notvisible' : 'icon-browse'"
             class="iconfont font-size-20 mar-rgt-5"
             @click.stop="widgetDisplayCtrl(data)"></i>
          <i :class="data.isLocked ? 'icon-shangsuo font-color-danger' : 'icon-kaisuo'"
             class="iconfont font-size-16"
             @click.stop="widgetLockCtrl(data)"></i>
        </div>
      </div>
      <div slot-scope="{data}" v-else class="custom-tree-node custom-tree-node-disabled">
        <span>{{data.name}}（已删除）</span>
      </div>
    </el-tree>
  </div>
</template>

<script>
  import {PageHandler} from "@/modules/IDE/pageHandler";
  import {WidgetFactory} from "@/modules/IDE/widgetFactory";
  import {confirmHandle} from "@/utils";
  import {mapActions, mapState} from "vuex";

  export default {
    name: 'AsideWidgetTree',
    props: {
	    editorType: {
		    type: String,
		    default: 'room', // room/component
	    },
      pageHdl: {
        type: PageHandler,
        default: () => {
          return undefined;
        }
      },
      homePageId: {
        type: String,
        default: ''
      },
	    isSorting: {
		    type: Boolean,
		    default: false
	    },
    },
    data() {
      return {
				treeRef: null,
	      treeData: [],
	      expandedKey: [],
	      rootNode: null, // 用于主动 loadNode
	      treeLoadResolve: null,
      };
    },
    computed: {
	    ...mapState({
		    curPageType: state => state.ide.curPageType,
	    }),
	    nodeClass() {
		    return (widget = {}) => {
			    const {id, isRoot, active} = widget;
			    if (active) {
				    return ['font-weight-bold', 'font-color-primary'];
			    }
					// 以下逻辑对 active 的 组件所属的 page 节点进行字体加粗
					if (!isRoot) return '';
					const {type, activePage = {}} = this.pageHdl;
			    if (this.curPageType === type && activePage.id === id) {
				    return ['font-weight-bold', 'font-gray-10'];
			    }
		    }
	    },
	    showDropdown() {
				return (widget) => {
          if (!widget.isRoot) return false;
					return !!this.dropdownItems(widget).length;
				}
	    },
      dropdownItems() {
				return (widget) => {
					const {type, pages = []} = this.pageHdl;
					const undeletedPages = pages.filter(page => !page.isDeleted);
					const {id, isAppendage,appendageId} = widget;
					let showDelete = type === 'page' && (id !== this.homePageId || undeletedPages.length > 1);
					const items = [
						{
							label: '复制',
							command: 'clone',
							show: type === 'page' ||type === 'subPage' || (isAppendage&&appendageId.length===0)
						},
						{
							label: '删除',
							command: 'delete',
							class: 'font-color-danger',
							show:  (isAppendage&&appendageId.length===0) || showDelete || type === 'subPage'
						},
						{
							label: '设为首页',
							command: 'home',
							class: 'font-color-primary',
							show: type === 'page'
						},
					];
					return items.filter(item => !!item.show);
				}
      },
    },
	  watch: {
	    'pageHdl.pages': {
				handler() {
					this.collapseAllNode();
					this.reloadNode();
				}
	    }
	  },
    mounted() {
			this.treeRef = this.$refs['widgetTree'];
      this.$EventBus.$on('selectWidget', (widget) => {
				// 判断当前选中的组件是否属于 pageHdl，防止事件通知执行多次
	      const {contain} = this.pageHdl.judgePageContainWidget(widget);
				if (!contain) return;
				// 如果当前选中的组件节点的子级已经被展开过，则点击节点时，不要将子节点折叠
	      // 通过 exceptCollapse 传入 collapseAllNode 方法
				const exceptCollapse = [];
				this.expandedKey.forEach(widgetId => {
					const fullPath = WidgetFactory.getWidgetFullPath(widgetId);
					if (fullPath.includes(widget.id)) {
						exceptCollapse.push(widgetId);
					}
				});
	      this.collapseAllNode(exceptCollapse);
	      this.autoExpandNode(widget);
      });
      this.$EventBus.$on('createWidgetGroup', (parent = {}) => {
	      const node = this.treeRef.getNode(parent.id);
	      if (!node) return;
	      node.childNodes = [];
	      this.loadNode(node, () => {});
      });
      this.$EventBus.$on('jumpToSubPage', (widget) => {
	      const {relateSubPage, relateSubPageId} = widget;
        if (relateSubPage) {
	        const nodeId = `treeNode-${relateSubPageId}`;
	        const element = document.getElementById(nodeId);
	        element && element.scrollIntoView({block: 'center', behavior: 'smooth'});
        }
      });
	    this.$EventBus.$on('undoRedoExecute', this.reloadNode);
      this.$EventBus.$on('tabSortExecute',  this.reloadNode);
      this.$EventBus.$on('pageViewSortExecute',  this.reloadNode);
      this.$EventBus.$on('deviceSortExecute',  this.reloadNode);
      // 移除el-tree组件键盘事件
	    this.treeRef.$el.removeEventListener('keydown', this.treeRef.handleKeydown);
    },
    beforeDestroy() {
      this.$EventBus.$off('selectWidget');
      this.$EventBus.$off('createWidgetGroup');
      this.$EventBus.$off('jumpToSubPage');
      this.$EventBus.$off('undoRedoExecute');
      this.$EventBus.$off('tabSortExecute');
      this.$EventBus.$off('pageViewSortExecute');
    },
    methods: {
      ...mapActions(['updateDraggingWidget']),
      pageOperation(page, command) {
        switch (command) {
          case 'clone':
            const newPage = this.pageHdl.clonePage(page);
            this.$EventBus.$emit('selectWidget', this.pageHdl.activePage);
	          const widgets = WidgetFactory.getWidgetFlattenChildren(newPage);
	          WidgetFactory.undoRedoHdl.operationHdl([{operationType: 'add', widgets: widgets}]);
            break;
          case 'delete':
            confirmHandle({label: `确定要删除页面：${page.name} 吗?`}).then(() => {
              const deletedWidgets = this.pageHdl.deletePage(page);
              this.$EventBus.$emit('selectWidget', this.pageHdl.activePage);
              // 删除页面后收起节点
              const pageNode = this.treeRef.getNode(page.id);
              pageNode.expanded = false;
	            WidgetFactory.undoRedoHdl.operationHdl([{operationType: 'delete', widgets: deletedWidgets}]);
            }).catch(() => {
            });
            break;
            case 'home':
            this.$emit('setHomepage', page.id);
            break;
          default:
            break;
        }
      },
	    loadNode(node, resolve) {
		    const {level = 0, data = {}} = node;
				if (level === 0) {
					this.rootNode = node;
					this.treeLoadResolve = resolve;
					resolve(this.pageHdl.pages);
				} else {
					resolve(data.children);
				}
	    },
	    reloadNode() {
		    if (!this.rootNode) return;
		    this.rootNode.childNodes = [];
		    this.loadNode(this.rootNode, this.treeLoadResolve);
	    },
	    // 自动展开选中 widget 的父节点
	    autoExpandNode(widget = {}) {
				const {parentId = ''} = widget;
				if (!parentId) return;
				const parent = WidgetFactory.getWidgetById(parentId);
				if (!parent) return;
				if (!this.expandedKey.includes(parentId)) {
					this.expandedKey.push(parentId);
				}
				this.autoExpandNode(parent);
	    },
	    // 折叠所有节点
	    collapseAllNode(exceptCollapse = []) {
		    this.expandedKey.forEach(widgetId => {
					if (exceptCollapse.includes(widgetId)) return;
			    const node = this.treeRef.getNode(widgetId);
			    node && (node.expanded = false);
		    });
		    this.expandedKey = exceptCollapse;
	    },
	    nodeExpand(data) {
				const widgetId = data.id;
				if (this.expandedKey.includes(widgetId)) return;
		    this.expandedKey.push(widgetId);
	    },
	    nodeCollapse(data) {
		    const widgetId = data.id;
				const idx = this.expandedKey.indexOf(widgetId);
				!!~idx && this.expandedKey.splice(idx, 1);
	    },
	    // 判断是否为叶子节点
	    judgeLeafNode(data = {}) {
				const {children = [], relateSubPage = false, isDeleted = false} = data;
				return !children.length || relateSubPage || isDeleted;
	    },
      widgetDisplayCtrl(widget = {}) {
        widget.display = !widget.display;
				// 与组件选择器状态进行同步
	      widget.displayForPicker = widget.display;
      },
      widgetLockCtrl(widget = {}) {
        widget.isLocked = !widget.isLocked;
      },
      allowDrag(node) {
				if (this.pageHdl.type !== 'subPage' && !this.isSorting) return false;
        const {data = {}} = node;
				const {selectable, draggable, isLocked, isFreeze, isDeleted} = data;
        return selectable && draggable && !isLocked && !isFreeze && !isDeleted;
      },
      allowDrop(dragNode, dropNode, type) {
				if (!this.isSorting) return false;
	      const {data: dragData = {}} = dragNode;
	      const {data: dropData = {}} = dropNode;
				if (dragData.isRoot) {
					if (type === 'inner') return false;
					return dropData.isRoot;
				} else {

					switch (type) {
						case 'inner':
							return !dropData.isDeleted && dropData.droppable;
						case 'prev':
						case 'next':
							 if (dropData.isRoot) return false;
							const parent = WidgetFactory.getWidgetById(dropData.parentId);
							if (!parent) return false;
							return !parent.isDeleted && parent.droppable;
						default:
							return false;
					}
				}

      },
      nodeDragStart(node = {}) {
        const widget = node.data;
        if (widget.type !== 'subPage') return;
        this.updateDraggingWidget(widget);
      },
      nodeDragEnd() {
        this.updateDraggingWidget(undefined);
      },
      nodeDrop(dragNode, dropNode, type) {
	      dropNode.expanded = true;
	      const {data: dragData = {}} = dragNode;
	      const {data: dropData = {}} = dropNode;
	      const dragWidget = WidgetFactory.getWidgetById(dragData.id);
	      this.pageHdl.updateActivePage(dragWidget);
				this.$nextTick(() => {
					// 如果是更改了被拖拽组件的父级，则设置其位置为 (0, 0)，并维护 parentId 关联
					switch (type) {
						case 'inner':
							if (dragWidget.parentId !== dropData.id) {
								dragWidget.rect.left = 0;
								dragWidget.rect.top = 0;
								dragWidget.parentId = dropData.id;
							}
							break;
						case 'before':
						case 'after':
							if (dragWidget.parentId !== dropData.parentId) {
								dragWidget.rect.left = 0;
								dragWidget.rect.top = 0;
								dragWidget.parentId = dropData.parentId;
							}
							break;
						default:
							break;
					}
          if(dragWidget.isRoot){
            //给根页面重新赋值排序
            const {childNodes}=this.rootNode
            const updatedArray = childNodes.map((item, index) => {
              return {...item, data: {...item.data,sortNo: index + 1} };
            });
            // 创建一个映射，将 a 数组中的 id 映射到它们的索引
            const aMap = updatedArray.reduce((acc, item, index) => {
              acc[item.data.id] = index;
              return acc;
            }, {});
            // 根据 a 数组中的 id 对 b 数组进行排序
            this.pageHdl.pages.sort((x, y) => aMap[x.id] - aMap[y.id]);
          }
					 this.pageHdl.refreshPageWidgetSortNo();
				});
      },
      nodeClick(widget = {}) {
        if (widget.isDeleted || !widget.selectable) return;
        this.$emit('selectPage');
        this.$nextTick(() => {
          this.pageHdl.updateActivePage(widget);
          this.$EventBus.$emit('selectWidget', widget);
        });
      },
    }
  };
</script>

<style scoped lang="less">

  .widget-tree-container {

    .custom-tree-node {
      display: flex;
      flex: 1;
      justify-content: space-between;
      align-items: center;
      height: 100%;
      padding-right: 10px;
      font-size: 14px;

	    .custom-tree-name {
		    display: inline-block;
		    max-width: 150px;
		    text-overflow: ellipsis;
		    overflow: hidden;
	    }
    }

    .custom-tree-node-disabled {
      cursor: not-allowed;
      text-decoration: line-through;
    }

    /deep/ .el-tree {
      border-radius: 4px;

      .el-tree-node__content {
        height: 35px !important;
        border-bottom: 1px solid @colorGray96;
      }
    }
  }
</style>
